package simpledb.common;

import simpledb.storage.BufferPool;
import simpledb.storage.LogFile;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Database 类负责初始化数据库系统的静态组件，如目录、缓冲池和日志文件,并提供了静态方法来访问这些组件。
 * 它使用单例模式保证整个应用程序只有一个实例存在，并且通过 AtomicReference 来确保线程安全。
 *
 * @Threadsafe 线程安全
 */
public class Database {

    // 使用 AtomicReference 保证线程安全地持有单例实例
    private static final AtomicReference<Database> _instance   = new AtomicReference<>(new Database());

    // 数据库目录
    private final Catalog                          _catalog;

    // 缓冲池
    private final BufferPool                       _bufferpool;

    // 日志文件名
    private final static String                    LOGFILENAME = "log";

    // 日志文件对象
    private final LogFile                          _logfile;

    /**
     * 私有构造函数，防止外部实例化。
     * 初始化目录、缓冲池和日志文件。
     */
    private Database() {
        _catalog = new Catalog(); // 创建一个新的目录实例
        _bufferpool = new BufferPool(BufferPool.DEFAULT_PAGES); // 创建一个新的缓冲池实例，默认页面数

        LogFile tmp = null;
        try {
            // 尝试创建一个新的日志文件实例
            tmp = new LogFile(new File(LOGFILENAME));
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1); // 如果无法创建日志文件，则退出程序
        }
        _logfile = tmp; // 设置日志文件实例
        // startControllerThread(); 可能用于启动控制线程（注释掉了）
    }

    /**
     * 获取静态 Database 实例的日志文件。
     *
     * @return 日志文件实例
     */
    public static LogFile getLogFile() {
        return _instance.get()._logfile;
    }

    /**
     * 获取静态 Database 实例的缓冲池。
     *
     * @return 缓冲池实例
     */
    public static BufferPool getBufferPool() {
        return _instance.get()._bufferpool;
    }

    /**
     * 获取静态 Database 实例的目录。
     *
     * @return 目录实例
     */
    public static Catalog getCatalog() {
        return _instance.get()._catalog;
    }

    /**
     * 用于测试的方法 - 创建一个新的缓冲池实例并返回它。
     *
     * @param pages 新缓冲池的页面数
     * @return 新的缓冲池实例
     */
    public static BufferPool resetBufferPool(int pages) {
        java.lang.reflect.Field bufferPoolF = null;
        try {
            // 使用反射设置新的缓冲池实例
            bufferPoolF = Database.class.getDeclaredField("_bufferpool");
            bufferPoolF.setAccessible(true);
            bufferPoolF.set(_instance.get(), new BufferPool(pages));
        } catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException | SecurityException e) {
            e.printStackTrace();
        }
        return _instance.get()._bufferpool;
    }

    /**
     * 重置数据库，仅用于单元测试。
     */
    public static void reset() {
        _instance.set(new Database()); // 创建一个新的 Database 实例
    }
}
